<?php
namespace Lib\Source;

use Lib\Source\DriverException,
    Lib\Source\DriverInterface,
    Lib\Data;

class DriverAbstract implements DriverInterface{
 
    /**
     * Global data storage
     * 
     * @var Data
     */
    protected $_storage;
    
    /**
     * @var Data
     */
    protected $_options;
    
    /**$data
     * Default constructor
     * @param mixed $options
     */
    final public function __construct($options = array()){
        $this->setOptions($options);
        $this->init();
    }
    
    /**
     * @see Lib\Source.DriverInterface::init()
     */
    public function init(){}

    /**
     * @see Lib\Source.DriverInterface::load($name, $params)
     */
    public function load($name, $default = null){
        throw new DriverException('You need to implement "load()" method');
    }
    
    /**
     * @see Lib\Source.DriverInterface::save($data)
     */
    public function save($name = null, $value = null){
        if (null === $name) {                             // Save all data
            if(count($this->getStorage())){
                return $this->saveData($this->getStorage());
            } else {                                      // There is any data
                return false;
            }
        } elseif(Data::is_array_accessible($name)){
            if(!count($name)) return false;
            return $this->saveData($this->getStorage()->getValues($name));
        } elseif(null !== $value) {
            $this->getStorage()->setValue($name, $value);
            return $this->saveData(array($name, $value));
        } else {                                          // Save data specified by name
            if($this->getStorage()->offsetExists($name)){
                return $this->saveData(array($name => $this->getStorage()->getValue($name)));
            } else {
                return false;
            }
        }
    }
    
    /**
     * @see Lib\Source.DriverInterface::getStorage()
     */
    public function getStorage(){
        if(!$this->_storage instanceof Data){
            $this->_storage = new Data();
        }
        return $this->_storage;
    }
    
    /**
     * @see Lib\Source.DriverInterface::setStorage()
     */
    public function setStorage(Data $data){
        $this->_storage = $data;
    }
    
    /**
     * @see Lib\Source.DriverInterface::appendStorage()
     */
    public function appendStorage(Data $data){
        $this->_storage->append($data);
    }
    
    /**
     * @see Lib\Source.DriverInterface::setOptions()
     */
    public function setOptions($options = array()){
        if(! Data::is_array_accessible($options)){
            $options = new Data();
        } elseif(is_array($options)){
            $options = new Data($options);
        }
        $this->_options = $options;
    }
    
    /**
     * @see Lib\Source.DriverInterface::getOptions()
     */
    public function getOptions(){
        if(!$this->_options instanceof Data){
            $this->setOptions();
        }
        return $this->_options;
    }
    
    /**
     * @see Lib\Source.DriverInterface::getOption()
     */
    public function getOption($name, $default = null){
        $options = $this->getOptions();
        if (!$options->offsetExists($name)){
            return $default;
        }
        return $options->getValue($name);
    }
    
    /**
     * @see Lib\Source.DriverInterface::saveData()
     */
    public function saveData($data){
        throw new DriverException('You need to implement "saveData()" method');
    }
}